
// ===============================================================================================================
// -*- C++ -*-
//
// INIFile.hpp - Declaration of the INIFile class, for program configuration.
//
// Copyright (c) 2011 Guilherme R. Lampert
// guilherme.ronaldo.lampert@gmail.com
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// above is included in the resulting source code.
//
// ===============================================================================================================

#ifndef __INI_FILE_HPP__
#define __INI_FILE_HPP__

#include <CommLib.hpp>
#include <MathLib.hpp>
#include <list>
#include <map>

namespace CommLib {

// =========================================================
// INI file section.
// =========================================================

class INISection {

	friend class INIFile;

public:

	INISection(const std::string & sectionName);

	// Get an integer value from the INI section, based on a key.
	bool GetInteger(const std::string & key, int & val) const;

	// Get a float value from the INI section, based on a key.
	bool GetFloat(const std::string & key, float & val) const;

	// Get a string from the INI section, based on a key.
	bool GetString(const std::string & key, std::string & val) const;

	// Get a vector value from the INI section, based on a key.
	bool GetVector(const std::string & key, MathLib::Vec3f & val) const;

	// Get the section name (Read only).
	inline const std::string & GetName(void) const { return (name); }

	// Get the number of properties in this section.
	inline int GetNumProperties(void) const { return (lines.size()); }

	~INISection(void);

private:

	// Private Data:

	std::string name;
	std::list<const std::string> lines;
};

// =========================================================
// Standard .INI file parsing.
// Supports sections and comments as ';' or '#'.
// =========================================================

class INIFile {

public:

	typedef std::map<const std::string, const INISection *> SectionMap;

	INIFile(void) : sections() { /**/ };

	// Read an .INI file if 'fileName' is given.
	INIFile(const std::string & iniFile);

	// Read an .INI file and split it into sections. If no sections are present, a "Global" section is defined.
	bool Read(const std::string & iniFile);

	// Return pointer to a section, or null if the section does not exist.
	// If 'strict' is false, the function tries to find the closest match to 'sectionName' if that exact section is not defined.
	const INISection * GetSection(const std::string & sectionName = "Global", bool strict = true) const;

	// Return all loaded sections for the current .INI file.
	inline const SectionMap & GetAllSections(void) const { return (sections); }

	// Return the number of sections loaded.
	inline int GetNumSections(void) const { return (sections.size()); }

	// Delete all loaded sections and data.
	void Clear(void);

	// Destructor does automatic cleanup.
	~INIFile(void);

private:

	SectionMap sections;
};

}; // namespace CommLib {}

#endif // __INI_FILE_HPP__